package com.zhijian.medical.service;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.zhijian.medical.dao.local.RoutineSampleBrRecordDetailMapper;
import com.zhijian.medical.dao.local.RoutineSampleBrRecordMapper;
import com.zhijian.medical.dao.local.RoutineSingleSampleQpMapper;
import com.zhijian.medical.entity.dto.PersonDto;
import com.zhijian.medical.entity.po.RoutinePatientDiagnose;
import com.zhijian.medical.entity.po.RoutineSampleBrRecord;
import com.zhijian.medical.entity.po.RoutineSampleBrRecordDetail;
import com.zhijian.medical.entity.vo.request.RoutineSampleArchiveSearchVo;
import com.zhijian.medical.entity.vo.request.RoutineSampleBrRecordSearchVo;
import com.zhijian.medical.entity.vo.response.RoutinePatientDiagnoseVo;
import com.zhijian.medical.entity.vo.response.RoutineSampleArchiveVo;
import com.zhijian.medical.holder.CurrentUserHolder;
import com.zhijian.medical.util.AssertUtil;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.util.*;

/**
 * 借还片记录业务处理
 */
@Service
public class RoutineSampleBrRecordService {

    @Autowired
    RoutineSampleBrRecordMapper routineSampleBrRecordMapper;

    @Autowired
    RoutineSampleBrRecordDetailMapper routineSampleBrRecordDetailMapper;

    @Autowired
    RoutineSingleSampleQpMapper routineSingleSampleQpMapper;

    @Autowired
    CacheService cacheService;

    public com.zhijian.util.page.Page<RoutineSampleBrRecord> selectPageList(RoutineSampleBrRecordSearchVo searchVo){
        handleReqParam(searchVo);
        PageHelper.startPage(searchVo.getPageNum(), searchVo.getPageSize());
        Page<RoutineSampleBrRecord> dataPage = routineSampleBrRecordMapper.selectPage(searchVo);
        for (RoutineSampleBrRecord record : dataPage.getResult()){
            if (StringUtils.isNotBlank(record.getBrQpData())){
                String[] brDataArr = record.getBrQpData().split(",");
                record.setBrQpNum(brDataArr.length);
            }
            if (StringUtils.isNotBlank(record.getBrLkData())){
                String[] brDataArr = record.getBrLkData().split(",");
                record.setLkNum(brDataArr.length);
            }
        }
        com.zhijian.util.page.Page<RoutineSampleBrRecord> result =
                new com.zhijian.util.page.Page<>(true,
                        Integer.parseInt( String.valueOf(dataPage.getTotal())), searchVo.getPageNum(), searchVo.getPageSize());
        result.setData(dataPage.getResult());
        return result;
    }

    private void handleReqParam(RoutineSampleBrRecordSearchVo searchVo){
        String blhQuery = searchVo.getConventionPathologyNumber();
        String qpNumberQuery = searchVo.getQpNumber();
        String lkNumberQuery = searchVo.getLkNumber();
        String brNumberQuery = searchVo.getBrCode();
        if (org.springframework.util.StringUtils.hasText(blhQuery)){
            if (blhQuery.contains("~")){
                String[] val = blhQuery.split("~");
                Set<String> blhList = new LinkedHashSet<>();
                AssertUtil.check(val.length != 2, "病理号查询条件异常");
                String prefix = val[0].substring(0, val[0].length() - 5);
                int startIndex = Integer.parseInt(val[0].substring(val[0].length() - 5));
                int endIndex = Integer.parseInt(val[1]);
                int i = 0;
                for ( ;startIndex <= endIndex; startIndex++){
                    String code = org.apache.commons.lang3.StringUtils.leftPad(String.valueOf(startIndex), 5 ,"0");
                    blhList.add(prefix + code);
                    i++;
                    if (i>100){
                        break;
                    }
                }
                searchVo.setBlhList(new LinkedList<>(blhList));
            }else {
                List<String> blhList = new LinkedList<>();
                blhList.add(blhQuery);
                searchVo.setBlhList(blhList);
            }
        }
        if (org.springframework.util.StringUtils.hasText(qpNumberQuery)){
            if (qpNumberQuery.contains("~")){
                String[] val = qpNumberQuery.split("~");
                Set<String> blhList = new LinkedHashSet<>();
                AssertUtil.check(val.length != 2, "病理号查询条件异常");
                String prefix = val[0];
                String newPrefix = prefix.substring(0, prefix.lastIndexOf("-"));
                int startIndex = Integer.parseInt(prefix.substring(prefix.lastIndexOf("-") + 1));
                int endIndex = Integer.parseInt(val[1]);
                int i = 0;
                for ( ;startIndex <= endIndex; startIndex++){
                    blhList.add(newPrefix + "-" + startIndex);
                    i++;
                    if (i>100){
                        break;
                    }
                }
                searchVo.setQpList(new LinkedList<>(blhList));
            }else {
                List<String> numberList = new LinkedList<>();
                numberList.add(qpNumberQuery);
                searchVo.setQpList(numberList);
            }
        }
        if (org.springframework.util.StringUtils.hasText(lkNumberQuery)){
            if (lkNumberQuery.contains("~")){
                String[] val = lkNumberQuery.split("~");
                Set<String> blhList = new LinkedHashSet<>();
                AssertUtil.check(val.length != 2, "病理号查询条件异常");
                String prefix = val[0];
                String newPrefix = prefix.substring(0, prefix.lastIndexOf("-"));
                int startIndex = Integer.parseInt(prefix.substring(prefix.lastIndexOf("-") + 1));
                int endIndex = Integer.parseInt(val[1]);
                int i = 0;
                for ( ;startIndex <= endIndex; startIndex++){
                    blhList.add(newPrefix + "-" + startIndex);
                    i++;
                    if (i>100){
                        break;
                    }
                }
                searchVo.setLkList(new LinkedList<>(blhList));
            }else {
                List<String> numberList = new LinkedList<>();
                numberList.add(lkNumberQuery);
                searchVo.setLkList(numberList);
            }
        }
        if (org.springframework.util.StringUtils.hasText(brNumberQuery)){
            if (brNumberQuery.contains("~")){
                String[] val = brNumberQuery.split("~");
                Set<String> blhList = new LinkedHashSet<>();
                AssertUtil.check(val.length != 2, "病理号查询条件异常");
                String prefix = val[0].substring(0, val[0].length() - 5);
                int startIndex = Integer.parseInt(val[0].substring(val[0].length() - 5));
                int endIndex = Integer.parseInt(val[1]);
                int i = 0;
                for ( ;startIndex <= endIndex; startIndex++){
                    String code = org.apache.commons.lang3.StringUtils.leftPad(String.valueOf(startIndex), 5 ,"0");
                    blhList.add(prefix + code);
                    i++;
                    if (i>100){
                        break;
                    }
                }
                searchVo.setBrCodeList(new LinkedList<>(blhList));
            }else {
                List<String> blhList = new LinkedList<>();
                blhList.add(brNumberQuery);
                searchVo.setBrCodeList(blhList);
            }
        }
    }

    public RoutineSampleBrRecord readOne(Long id){
        RoutineSampleBrRecord record = routineSampleBrRecordMapper.selectById(id);
        List<RoutineSampleBrRecordDetail> detailList = borrowData(id);
        List<RoutineSampleBrRecordDetail> needShow = new LinkedList<>();
        for (RoutineSampleBrRecordDetail routineSampleBrRecordDetail : detailList){
            if(!RecordType.GH.getCode().equals(routineSampleBrRecordDetail.getState())){
                needShow.add(routineSampleBrRecordDetail);
            }
            routineSampleBrRecordDetail.setType(record.getJyType());
        }
        for (RoutineSampleBrRecordDetail detail : detailList){
            String[] numberArr = detail.getNumber().split("-");
            detail.setConventionPathologyNumber(numberArr[0]);
        }
        record.setDetailList(needShow);
        return record;
    }

    @Transactional(rollbackFor = Exception.class, value = "localTransactionManager")
    public RoutineSampleBrRecord addRsb(RoutineSampleBrRecord routineSampleBrRecord){
        Date now = new Date();
        PersonDto personDto = CurrentUserHolder.getUser();
        routineSampleBrRecord.setCreateTime(now);
        routineSampleBrRecord.setUpdateTime(now);
        routineSampleBrRecord.setJyOperate(personDto.getId());
        routineSampleBrRecord.setJyOperater(personDto.getName());
        String jyData = String.join(",", routineSampleBrRecord.getBrDataList());
        if (CollectionUtil.isNotEmpty(routineSampleBrRecord.getBrDataList())){
            String number = routineSampleBrRecord.getBrDataList().get(0);
            String[] numberArr = number.split("-");
            routineSampleBrRecord.setBlh(numberArr[0]);
        }
        if (RoutineSampleArchiveService.ArchiveType.QP.getCode().equals(routineSampleBrRecord.getJyType())){
            routineSampleBrRecord.setBrQpData(jyData);
            routineSampleBrRecord.setBrQpNum(routineSampleBrRecord.getBrDataList().size());
        }else {
            routineSampleBrRecord.setBrLkData(jyData);
            routineSampleBrRecord.setLkNum(routineSampleBrRecord.getBrDataList().size());
        }
        routineSampleBrRecord.setJyState(RecordType.NO.getCode());
        int year = LocalDate.now().getYear();
        String key = "br_redis_prefix_" + year;
        Long idx = cacheService.incr(key);
        String code = StringUtils.leftPad(String.valueOf(idx), 5, "0");
        routineSampleBrRecord.setBrCode("BR" + year + code);
        routineSampleBrRecordMapper.insert(routineSampleBrRecord);
        if (CollectionUtil.isNotEmpty(routineSampleBrRecord.getBrDataList())){
            recordDetail(routineSampleBrRecord.getBrDataList(), routineSampleBrRecord.getId());
        }
        return routineSampleBrRecord;
    }

    public RoutinePatientDiagnoseVo readDiagnoseVo(RoutinePatientDiagnose searchVo){
        return routineSingleSampleQpMapper.readDiagnoseVo(searchVo);
    }

    public RoutineSampleBrRecord updateRsb(RoutineSampleBrRecord routineSampleBrRecord){
        Date now = new Date();
        routineSampleBrRecord.setUpdateTime(now);
        String jyData = String.join(",", routineSampleBrRecord.getBrDataList());
        if (CollectionUtil.isNotEmpty(routineSampleBrRecord.getBrDataList())){
            String number = routineSampleBrRecord.getBrDataList().get(0);
            String[] numberArr = number.split("-");
            routineSampleBrRecord.setBlh(numberArr[0]);
        }
        if (RoutineSampleArchiveService.ArchiveType.QP.getCode().equals(routineSampleBrRecord.getJyType())){
            routineSampleBrRecord.setBrQpData(jyData);
            routineSampleBrRecord.setBrQpNum(routineSampleBrRecord.getBrDataList().size());
        }else {
            routineSampleBrRecord.setBrLkData(jyData);
            routineSampleBrRecord.setLkNum(routineSampleBrRecord.getBrDataList().size());
        }
        routineSampleBrRecordMapper.updateById(routineSampleBrRecord);
        if (CollectionUtil.isNotEmpty(routineSampleBrRecord.getBrDataList())){
            delDetail(routineSampleBrRecord.getId());
            recordDetail(routineSampleBrRecord.getBrDataList(), routineSampleBrRecord.getId());
        }
        return routineSampleBrRecord;
    }

    /**
     * 归还
     * @param routineSampleBrRecord 保存
     * @return
     */
    @Transactional(rollbackFor = Exception.class, value = "localTransactionManager")
    public RoutineSampleBrRecord ghRsb(RoutineSampleBrRecord routineSampleBrRecord){
        List<String> rtn = routineSampleBrRecord.getBrDataList();
        PersonDto personDto = CurrentUserHolder.getUser();
        if (CollectionUtil.isNotEmpty(rtn)){
            List<RoutineSampleBrRecordDetail> recordDetails = borrowData(routineSampleBrRecord.getId());
            if (rtn.size() == recordDetails.size()){
                routineSampleBrRecord.setJyState(RecordType.GH.getCode());
            }else {
                routineSampleBrRecord.setJyState(RecordType.BF.getCode());
                long noGh = recordDetails.stream().filter(e -> !RecordType.GH.getCode().equals(e.getState())).count();
                //未归还与提交归还的一致。则数据状态改为归还
                if (rtn.size() == Integer.parseInt(noGh + "")){
                    routineSampleBrRecord.setJyState(RecordType.GH.getCode());
                }
            }
            updateState(rtn, routineSampleBrRecord.getId());
        }
        routineSampleBrRecord.setGhDate(new Date());
        routineSampleBrRecord.setGhOperate(personDto.getId());
        routineSampleBrRecord.setGhOperater(personDto.getName());
        routineSampleBrRecordMapper.updateById(routineSampleBrRecord);
        return routineSampleBrRecord;
    }

    public List<RoutineSampleBrRecordDetail> borrowData(Long recordId){
        QueryWrapper<RoutineSampleBrRecordDetail> detailQuery = new QueryWrapper<>();
        detailQuery.eq("record_id", recordId);
        return routineSampleBrRecordDetailMapper.selectList(detailQuery);
    }

    private void updateState(List<String> rtn, Long recordId){
        QueryWrapper<RoutineSampleBrRecordDetail> updQuery = new QueryWrapper<>();
        updQuery.in("number", rtn);
        updQuery.eq("record_id", recordId);
        RoutineSampleBrRecordDetail upd = new RoutineSampleBrRecordDetail();
        upd.setState(QpLkDetailType.GH.getCode());
        routineSampleBrRecordDetailMapper.update(upd, updQuery);
    }

    private void recordDetail(List<String> numberList, Long recordId){
        for (String  number : numberList){
            RoutineSampleBrRecordDetail addObj = new RoutineSampleBrRecordDetail();
            addObj.setRecordId(recordId);
            addObj.setNumber(number);
            addObj.setState(QpLkDetailType.CJ.getCode());
            routineSampleBrRecordDetailMapper.insert(addObj);
        }
    }

    private void delDetail(Long recordId){
        QueryWrapper<RoutineSampleBrRecordDetail> delQuery = new QueryWrapper<>();
        delQuery.eq("record_id", recordId);
        routineSampleBrRecordDetailMapper.delete(delQuery);
    }

    @Getter
    @AllArgsConstructor
    public enum QpLkDetailType{

        /**
         * 已归档
         */
        GD(0),

        /**
         * 已出借
         */
        CJ(1),

        /**
         * 已归还
         */
        GH(2);

        private Integer code;

    }

    @Getter
    @AllArgsConstructor
    public enum RecordType{

        /**
         * 未归还
         */
        NO(0),

        /**
         * 部分归还
         */
        BF(1),

        /**
         * 归还
         */
        GH(2);

        private Integer code;

    }
}
